package com.huawei.hwclouds.lubanops.demo.common.client.impl;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Properties;

import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import com.huawei.hwclouds.lubanops.demo.common.client.HeaderFactory;
import com.huawei.hwclouds.lubanops.demo.common.exception.common.InternalErrorException;

/**
 * 通过证书访问https请求的客户端，主要是内部调用之间采用 <br>
 *
 * @author y00438022
 * @since 2020年2月28日
 */
public class ApacheHttpClientSSL extends ApacheHttpClientBase {

    protected PoolingHttpClientConnectionManager connectionManager;

    private CloseableHttpClient httpClient;

    public ApacheHttpClientSSL(String configContext, int maxTotal, int idleTimeInSeconds, int defaultTimeout) {
        super(defaultTimeout);
        this.init(configContext, maxTotal, idleTimeInSeconds);
    }

    public ApacheHttpClientSSL(String configContext, int maxTotal, int idleTimeInSeconds, int defaultTimeout,
        HeaderFactory factory) {
        super(defaultTimeout, factory);
        this.init(configContext, maxTotal, idleTimeInSeconds);
    }

    /**
     * 根据参数创建HTTP_CLIENT对象 <br>
     *
     * @author y00438022
     * @since 2020年2月28日
     */

    protected void init(String configContext, int maxTotal, int idleTimeInSeconds) {
        String configPath = configContext + "/client.properties";
        SSLContext sslContext = null;

        try (InputStream configInput = ApacheHttpClientSSL.class.getClassLoader().getResourceAsStream(configPath);
            InputStream clientInput = ApacheHttpClientSSL.class.getClassLoader()
                .getResourceAsStream(configContext + "/apm2clientcert.jks");
            InputStream trustInput = ApacheHttpClientSSL.class.getClassLoader()
                .getResourceAsStream(configContext + "/apm2clientcert.jks");) {
            if (configInput == null) {
                throw new InternalErrorException("config file not exists:" + configPath);
            }
            Properties config = new Properties();
            config.load(configInput);
            String sslPwd = config.getProperty("trust-store-password");

            KeyStore trustStore = KeyStore.getInstance("jks");
            trustStore.load(trustInput, sslPwd.toCharArray());
            KeyStore clientKeyStore = KeyStore.getInstance("jks");
            clientKeyStore.load(clientInput, sslPwd.toCharArray());

            sslContext = SSLContexts.custom()
                .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
                .loadKeyMaterial(clientKeyStore, sslPwd.toCharArray())
                .setSecureRandom(new SecureRandom())
                .useSSL()
                .build();
        } catch (KeyManagementException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (NoSuchAlgorithmException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (KeyStoreException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (IOException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (CertificateException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (UnrecoverableKeyException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        }

        connectionManager = (PoolingHttpClientConnectionManager) ApacheHttpClientHelp.getConnectionManager(sslContext);
        httpClient = (CloseableHttpClient) ApacheHttpClientHelp.getHttpclient(connectionManager,idleTimeInSeconds);
    }

    @Override
    protected CloseableHttpClient getHttpClient() {
        return httpClient;
    }

}
